package org.siteanalyser.service.impl;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.siteanalyser.domain.Message;
import org.siteanalyser.service.Service;
import org.siteanalyser.service.SystemException;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter;
import org.springframework.web.client.RestTemplate;

public class GoogleServiceImpl implements Service {
    private static final Log log = LogFactory.getLog(GoogleServiceImpl.class);
    private String version;
    private String endpoint;
    private String type;

    public void setType(final String type) {
        this.type = type;
    }

    public void setEndpoint(final String endpoint) {
        this.endpoint = endpoint.concat("?v={v}&q={q}");
    }

    public void setVersion(final String version) {
        this.version = version;
    }

    public void process(final Message message) throws SystemException {
        final RestTemplate restTemplate = initialiseTemplate();
        final String url = message.getRequest().getUrl();

        log.info(String.format("Querying Google with endpoint: %s, version: %s, url: %s", endpoint, version, url));
        final GoogleSearchResult response = restTemplate.getForObject(endpoint, GoogleSearchResult.class, version, url);
        if (type.equals("links")) {
            linksAnalysis(message, response);
        } else {
            feedsAnalysis(message, response);
        }
    }

    private void feedsAnalysis(final Message message, final GoogleSearchResult response) {
        final Object responseStatus = response.getResponseStatus();
        if (responseStatus != null) {
            if (responseStatus.toString().equals("200")) {
                message.getReport().addReportItem("rssfeeds", true);
            } else {
                message.getReport().addReportItem("rssfeeds", false);
            }
        }

    }

    @SuppressWarnings("unchecked")
    private void linksAnalysis(final Message message, final GoogleSearchResult response) {
        final LinkedHashMap<String, Object> cursor = (LinkedHashMap<String, Object>) response.getResponseData().get(
                "cursor");
        final String estimatedResultCount = (cursor.get("estimatedResultCount") == null ? "" : (String) cursor
                .get("estimatedResultCount"));
        message.getReport().addReportItem("indexedpages", estimatedResultCount);
    }

    private RestTemplate initialiseTemplate() {
        final RestTemplate restTemplate = new RestTemplate();
        final List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
        final MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter();
        converter.setSupportedMediaTypes(new ArrayList<MediaType>() {
            private static final long serialVersionUID = 1L;
            {
                add(new MediaType("text", "javascript"));
            }
        });
        list.add(converter);
        restTemplate.setMessageConverters(list);
        return restTemplate;
    }

    @SuppressWarnings("unused")
    private static class GoogleSearchResult {
        private LinkedHashMap<String, Object> responseData;
        private Object responseDetails;
        private Object responseStatus;

        public LinkedHashMap<String, Object> getResponseData() {
            return responseData;
        }

        public void setResponseData(final LinkedHashMap<String, Object> responseData) {
            this.responseData = responseData;
        }

        public Object getResponseDetails() {
            return responseDetails;
        }

        public void setResponseDetails(final Object responseDetails) {
            this.responseDetails = responseDetails;
        }

        public Object getResponseStatus() {
            return responseStatus;
        }

        public void setResponseStatus(final Object responseStatus) {
            this.responseStatus = responseStatus;
        }

    }

}